//
//  ViewController.m
//  蓝牙
//
//  Created by rimi on 16/5/27.
//  Copyright © 2016年 薛涛. All rights reserved.
//

#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>

/**  服务特征码 */
static NSString * const services_uuid = @"2CB3BE6D-5E96-4E7E-917E-74E35DEE64E8";
static NSString * const characteristic_read = @"5F47BE2C-1161-4CB9-A8AA-54A82F4D4AA0";
static NSString * const characteristic_write = @"33268A01-3313-4A81-991C-9C19658FF107";
static NSString * const characteristic_notifi = @"90885BEF-8910-474E-B6BD-455F7F314C5F";
@interface ViewController ()<CBCentralManagerDelegate,CBPeripheralDelegate>
/**  中心端管理者 */
@property (nonatomic, strong) CBCentralManager *centralManager;
/**  中心端管理者所扫描的服务 */
@property (nonatomic, strong) NSArray *serviceUUIDArray;
/**  成功链接的外围设备数组 */
@property (nonatomic, strong) NSMutableArray *peripherArray;
/**  服务写数据特征 */
@property (nonatomic, strong) CBCharacteristic *writeCharacteristic;
@property (strong, nonatomic) IBOutlet UILabel *disPlaylabel;
@property (strong, nonatomic) IBOutlet UITextField *textField;

@end

@implementation ViewController
#pragma mark - 类方法

#pragma mark - 创建方法

#pragma mark - 生命周期
- (void)viewDidLoad {
    [super viewDidLoad];
    [self initData];
    [self initUI];
    [self registerNotification];
}
#pragma mark - 实例方法
- (void)initData{
    self.serviceUUIDArray = @[[CBUUID UUIDWithString:services_uuid]];
    self.peripherArray = [NSMutableArray array];
}

- (void)initUI{
    [self centralManager];
}

- (void)registerNotification{
    
}
#pragma mark - 事件响应方法
- (IBAction)startSearchAdvertising:(UIBarButtonItem *)sender {
    if (self.centralManager.state == CBCentralManagerStatePoweredOn) {
        if (![self.centralManager isScanning]) {
            //扫描包含某服务的外围设备，若servies填写nil，则表示扫描所有的外围设备
            [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:services_uuid]] options:nil];
            NSLog(@"开始扫描");
        }else {
            [self.centralManager stopScan];
            NSLog(@"停止扫描");
        }
        sender.title = [self.centralManager isScanning] ? @"停止扫描":@"扫描";
    }else {
        NSLog(@"请开启蓝牙");
    }
}
- (IBAction)stopSearchAdvertising:(UIBarButtonItem *)sender {
    for (CBPeripheral *peripheral in self.peripherArray) {
        [self.centralManager cancelPeripheralConnection:peripheral];
    }
}
- (IBAction)msgSendBtn:(UIButton *)sender {
    [self.peripherArray.firstObject writeValue:[self.textField.text dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithResponse];
    self.textField.text = @"";
}
#pragma mark - CBCentralManagerDelegate Method
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    switch (central.state) {
        case CBCentralManagerStatePoweredOff:
            NSLog(@"蓝牙未打开");
            break;
        case CBCentralManagerStatePoweredOn:
            NSLog(@"蓝牙已打开");
            break;
        case CBCentralManagerStateUnsupported:
            NSLog(@"不支持蓝牙");
            break;
        case CBCentralManagerStateUnauthorized:
            NSLog(@"未验证蓝牙");
            break;
        case CBCentralManagerStateUnknown:
            NSLog(@"未知状态");
            break;
        case CBCentralManagerStateResetting:
            NSLog(@"重置状态");
            break;
        default:
            break;
    }
}
/**
 *  扫描到外围设备(服务端)时调用
 *
 *  @param central           中心端管理者
 *  @param peripheral        外围设备
 *  @param advertisementData 外围设备描述
 *  @param RSSI              信号强度
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
    NSLog(@"扫描到设备:%@,尝试链接",peripheral.name);
    //链接到外围设备
    [self.centralManager connectPeripheral:peripheral options:nil];
    //持有外围设备
    [self.peripherArray addObject:peripheral];
}

/**
 *  链接外围设备成功时调用
 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"链接到%@",peripheral.name);
    //链接成功后开始扫描服务，若此处填写nil相当于扫描外围设备所有的服务
    [peripheral discoverServices:self.serviceUUIDArray];
    //设置代理，查找到服务后回调其代理
    peripheral.delegate = self;
    
}
/**
 *  链接外围设备失败时调用
 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    if (error) {
        NSLog(@"链接到%@失败:%@",peripheral.name, error.localizedDescription);
    }
}

#pragma mark - CBPeripheralDelegate Method
/**
 *  扫描到外围设备的服务时调用
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    if (error) {
        NSLog(@"扫描服务失败:%@",error.localizedDescription);
        return;
    }
    NSLog(@"服务包含:%@",peripheral.services);
    //扫描服务内的特征
    [peripheral discoverCharacteristics:nil forService:peripheral.services[0]];
    
}
/**
 *  扫描完服务内部的特征时候调用
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {
        NSLog(@"扫描特征失败:%@",error.localizedDescription);
        return;
    }
    //针对于特征类型的不同，读取订阅也不同
    for (CBCharacteristic *characteristic in service.characteristics) {
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:characteristic_read]]) {
            //只读特征，直接读取特征内容
            [peripheral readValueForCharacteristic:characteristic];
        }else if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:characteristic_notifi]]) {
            //通知特征，需要订阅通知特征，这样当特征值有改变时会重新读取特征中的值
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }else if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:characteristic_write]]) {
            //只写特征，用于客户端写入数据，会在外围设备端由对应的方法读取所写内容
            self.writeCharacteristic = characteristic;
        }
    }
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    NSLog(@"读取特征值");
    self.disPlaylabel.text = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"更新特征值失败:%@",error.localizedDescription);
    }
    NSLog(@"有值更新");
}

#pragma mark - get方法

- (CBCentralManager *)centralManager {
    if (_centralManager == nil) {
        //queue设置同外围设备管理者相同，若设为nil则使用默认当前线程
        _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
    }
    return _centralManager;
}
@end
